// NIRMA STUDIO, 2013
// Object INIT
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <cstdlib>
#include <math.h>
#include <iomanip>

using namespace std;

class Object {
	public:
		int 		level,  	crit_chance, 	dodge_chance;
		int 		move_speed, attack_range, 	sight_range, 	cost[3];
		string 		name, 		armor_type, 	attack_type[2];
		float 		attack, 	health, 		mana, 	 		max_experience;
		float 		hp_regen, 	mana_regen, 	experience, 	exp_amount;
		bool 		alone, 		rested, 		aggro_idx, 		horrified;
		bool 		dead, x, y;

		Object();
		~Object();
		void 	stat();
		void 	ViewHp();
		float 	get_exp_amount(float hp, float mp, float dmg);
		void 	gain_exp(int x);
		void 	gain_level();
		void 	take_dmg(float dmg, string attack, int crit);
		bool 	DeadOrNot(bool dead_index, int exp_amount,Object *target);
		void 	fight(Object *target1, Object *target2);
};

Object::Object(){}

Object::~Object(){}

void Object::stat(){
	cout << endl;
	cout << "Name:      	" 	<< setw(10) << name                   << endl;
	cout << "Level:     	" 	<< setw(10) << level                  << endl;
	cout << "Health:    	" 	<< setw(10) << float(health)          << endl;
	cout << "Mana:      	" 	<< setw(10) << float(mana)            << endl;
	cout << "Attack:    	" 	<< setw(10) << float(attack)          << endl;
	cout << "Attack Type:   "  	<< setw(11) << attack_type[0]		  << endl;
	cout << "Armor Type:    "	<< setw(11) << armor_type[0]		  << endl;
	cout << "Crit Chance:   "  	<< setw(11) << crit_chance 			  << endl;
	cout << "Dodge Chance:  "  	<< setw(11) << dodge_chance 		  << endl;
	cout << "Move Speed: 	"	<< setw(10) << move_speed 			  << endl;
	cout << "Attack Range:  "	<< setw(11) << attack_range  		  << endl;
	cout << "Sight Range:   "	<< setw(11) << sight_range 			  << endl;
	cout << "HP Regen:      "	<< setw(11) << hp_regen 			  << endl;
	cout << "Mana Regen:    "	<< setw(11) << mana_regen 			  << endl;
	cout << "Experience:    " 	<< setw(11) << float(experience)      << endl;
	cout << "Max Experience:" 	<< setw(11) << float(max_experience)  << endl;
	cout << "Cost:          "	<< setw(2) << cost[0] << " / " << cost[1] << " / " << cost[2] << endl;
	cout << endl;
}

void Object::ViewHp(){
		cout << "-----------------------------"  << endl;
		cout << "Unit " <<  name << " have " <<
			float(health) << " health" << endl;
		cout << "-----------------------------"  << endl;
}

float Object::get_exp_amount(float hp, float mp, float dmg){
	float x = float((hp + (mp * 3) + (dmg * 5))/7);
	return x;
}

void Object::gain_exp(int x){
	experience += x;
	if(experience >= max_experience) Object::gain_level();
}

void Object::gain_level(){
	level 			 += 1;
	attack     		= attack * 1.2;
	health     		= health * 1.3;
	mana       		= mana 	 * 1.2;
	experience 		= 0;
	max_experience  = 10.0 * (pow(1.4, level));
}

void Object::take_dmg(float dmg, string attack, int crit){
	if(attack == armor_type) 			dmg *= 1.25;
	if((rand() % 100 + 1) <= crit) 		dmg *= 2;
	if((rand() % 100 + 1) > dodge_chance){
		health -= dmg;
		cout << name << "(" << health << ")" << " taken damage = " << float(dmg) << endl;
		if(health <= 0) dead = true;
	}
	else cout << name << " evoid attack" << endl;
}

bool Object::DeadOrNot(bool target_dead, int exp_amount, Object *target){
	if(target_dead == true){
		gain_exp(exp_amount);
		delete target;
		return true;
	}
	else return false;
}

void Object::fight(Object *target1, Object *target2){
	while(1){
	x = target1->DeadOrNot(target2->dead, target2->exp_amount, target2);
	y = target2->DeadOrNot(target1->dead, target1->exp_amount, target1);

	if(x){
		cout << endl;
		cout << target1->name << "(" << target1->health << ")" << " WON" << endl;
		cout << endl;
		break;
	}
	else{
		if(y){
			cout << endl;
			cout << target2->name << "(" << target2->health << ")" << " WON" << endl;
			cout << endl;
			break;
		}
		else{
			target2->take_dmg(target1->attack, target1->attack_type[1], target1->crit_chance);
			target1->take_dmg(target2->attack, target2->attack_type[1], target2->crit_chance);
		}
	}
	}
}